/*
 * Licensed this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.boapi.tax;

import java.util.Locale;
import java.util.concurrent.ConcurrentHashMap;

import org.boapi.core.IChecknumber;
import org.boapi.math.Mathfunctions;
import org.boapi.person.IIdentityDocument;
import org.boapi.person.PersonalIdentityCardFactory;
import org.boapi.util.CharSequenceHelper;

/**
 * <p lang='en'>
 * Representing the ID for inner European Union tax number called
 * value added tax registration number [VAT Reg.No.].
 * </p>
 * <p lang='de'>
 * Repräsentiert die allgemeine ID für den umsatzsteuerfreien
 * innergemeinschaftlichen Warenaustausch der Europäischen Union
 * Umsatzsteueridentifikationsmerkmal [UStID]
 * </p>
 * <p>
 *   <ul>
 *     <li lang='be'>le numéro d’identification à la taxe sur la valeur ajoutée BTW - identificatienummer</li>
 *     <li lang='bg'>Dank dobawena stoinost</li>
 *     <li lang='dk'>momsregistreringsnummer</li>
 *     <li lang='de'>Umsatzsteuer-Identifikationsnummer</li>
 *     <li lang='ee'>Käibemaksukohustuslase registreerimisnumber</li>
 *     <li lang='fi'>Arvonlisâverorekisterointi-numero</li>
 *     <li lang='fr'>le numéro d’identification à la taxe sur la valeur ajoutée</li>
 *     <li lang='gr'>Arithmos Forologikou Mitroou FPA</li>
 *     <li lang='en'>value added tax identification number</li>
 *     <li lang='it'>il numero di registrazione IVA</li>
 *     <li lang='lv'>pievienotāsvērtības nodokļa reģistrācijas numurs</li>
 *     <li lang='lt'>Pridetines vertes mo-kescio moketojo kodas</li>
 *     <li lang='nl'>BTW-identificatienummer</li>
 *     <li lang='pl'>Numer identyfikacji podatkowej</li>
 *     <li lang='pt'>o número de identificacao para efeitos do imposto sobre o valor acrescentado</li>
 *     <li lang='ro'>cod de înregistrare în scopuri de TVA</li>
 *     <li lang='se'>Registreringsnummer för mervärdesskatt (Momsnummer)</li>
 *     <li lang='sk'>Identifikačné číslo pre daň z pridanej hodnoty</li>
 *     <li lang='si'>davčna številka</li>
 *     <li lang='es'>el número de identificación a efectos del Impuesto sobre el Valor Anadido</li>
 *     <li lang='cz'>danove identifikacni cislo</li>
 *     <li lang='hu'>közösségi adószám</li>
 *     <li lang='cy'>Arithmos Egrafis FPA</li>
 *   </ul>
 * </p>
 * @author Sebastian Ritter
 * @version 1.0.0.0
 */
public final class VATRegNo implements IChecknumber {

	/**
	 * The value
	 */
	private String value = "";

	/** Defaultconstruktor */
    public VATRegNo (){
    }
    
    /**
     * Creates new object with VATRegNo
     * @param regNo
     */
    public VATRegNo (final String regNo) {
    	this.setCompleteValue(regNo);
    }

    /**
     * Return the value with leading county code 
     * @return
     */
    public String getValue () {
    	return this.value;
    }
    
	public boolean isChecknumberCorrect () {
		/* Sources:
		 * http://de.wikipedia.org/wiki/UStID
		 * www.bzst.bund.de Aufbau der Umsatzsteuer-Identifikationsnummer in den EU-Mitgliedstaaten Stand 23.02.2009
		 * Bundesgesetzblatt 1993 Teil I Seite 736
		 * http://www.pruefziffernberechnung.de/U/USt-IdNr.shtml
		 * http://en.wikipedia.org/wiki/Value_added_tax_identification_number
         */
		boolean ok = false;
		try {
		  if (this.value.length()>1) {
			if (this.value.startsWith("BE")) { // BE - BELGIEN
				int testnumber = -1;
				if (11 == this.value.length()) { // old values are 9 digits + country code...
					testnumber = Integer.parseInt(this.value.substring(2,8));
				}
				else if (12 == this.value.length()) {
					testnumber = Integer.parseInt(this.value.substring(2,9));
				}
				if (-1 != testnumber) { // length is ok
					final int mod97 = testnumber % 97;
					final int checknumber = Integer.parseInt(this.value.substring(this.value.length()-3));
					if (checknumber == (97 - mod97)) {
						ok = true;
					}
				}
			}
			else if (this.value.startsWith("BG")) { // BG - BULGARIEN
				if (this.value.length() == 11 || this.value.length() == 12) {
					Integer.parseInt(this.value.substring(2),10);
				}
			}
			else if (this.value.startsWith("DK")) { // DK - DÃ¤nemark
				final int sumOfDigits = Mathfunctions.sumOfDigits(Integer.parseInt(this.value.substring(2),10));
				if (sumOfDigits % 11 == 0) {
					ok = true;
				}
			}
			else if (this.value.startsWith("DE")) { // DE - Deutschland
				if (this.value.length() == 11) {
					int summe, produkt = 0;
					int [] ziffer = CharSequenceHelper.toIntArray(this.value.substring(2));
					for (int i = 0 ; i < ziffer.length -1; i++) {
						summe = produkt + ziffer[i];
						summe = summe % 10;
						if (0 == summe) {
							summe = 10;
						}
						produkt = (2*summe) % 11;
					}
					int pz = 11 - produkt;
					if (10 == pz) {
						pz = 0;
					}
					ok = ziffer [ziffer.length -1] == pz;
				}
			}
			else if (this.value.startsWith("EE")) { // EE - Estland
				if (this.value.length() == 11) {
					ok = true;
				}
			}
			else if (this.value.startsWith("FI")) { // FI - Finnland
				if (this.value.length() == 10) {
					final int [] factors = {7, 9, 10, 5, 8, 4, 2};
					final int [] products = Mathfunctions.multiply(factors, CharSequenceHelper.toIntArray(this.value.substring(2)));
					final int sum = Mathfunctions.sumOfNumbers(products, 0, products.length -2);
					int checkdigit = 11 - (sum%11);
					if (10 != checkdigit) {
						if (11 == checkdigit) {
							checkdigit = 0;
						}
						ok = Integer.parseInt(this.value.substring(this.value.length()-1)) == checkdigit;
					}
				}
			}
			else if (this.value.startsWith("FR")) { // FR - Frankreich
				if (this.value.length() == 13) {
					ok = true;
				}
			}
			else if (this.value.startsWith("EL")) { // EL - Griechenland !!!statt Country Language!!!
				if (this.value.length() == 11) {
					final int [] factors = {256, 128, 64, 32, 16, 8, 4, 2, 1};
					final int [] products = Mathfunctions.multiply(factors, CharSequenceHelper.toIntArray(this.value.substring(2)));
					final int sum = Mathfunctions.sumOfNumbers(products, 0, products.length -2);
					int checkdigit = sum % 11;
					if (checkdigit > 9) {
						checkdigit = 0;
					}
					ok = Integer.parseInt(this.value.substring(this.value.length()-1)) == checkdigit;
				}
			}
			else if (this.value.startsWith("IE")) { // IE - Irland
				final java.util.HashMap<Character, Integer> charIntCheckDigitMapping = new java.util.HashMap <Character, Integer>();
				charIntCheckDigitMapping.put('A', 1);
				charIntCheckDigitMapping.put('B', 2);
				charIntCheckDigitMapping.put('C', 3);
				charIntCheckDigitMapping.put('D', 4);
				charIntCheckDigitMapping.put('E', 5);
				charIntCheckDigitMapping.put('F', 6);
				charIntCheckDigitMapping.put('G', 7);
				charIntCheckDigitMapping.put('H', 8);
				charIntCheckDigitMapping.put('I', 9);
				charIntCheckDigitMapping.put('J', 10);
				charIntCheckDigitMapping.put('K', 11);
				charIntCheckDigitMapping.put('L', 12);
				charIntCheckDigitMapping.put('M', 13);
				charIntCheckDigitMapping.put('N', 14);
				charIntCheckDigitMapping.put('O', 15);
				charIntCheckDigitMapping.put('P', 16);
				charIntCheckDigitMapping.put('Q', 17);
				charIntCheckDigitMapping.put('R', 18);
				charIntCheckDigitMapping.put('S', 19);
				charIntCheckDigitMapping.put('T', 20);
				charIntCheckDigitMapping.put('U', 21);
				charIntCheckDigitMapping.put('V', 22);
				charIntCheckDigitMapping.put('W', 0);
				if (this.value.length() == 10 && charIntCheckDigitMapping.containsKey(this.value.charAt(9))) {
					String workValue = this.value.substring(2);
					final boolean oldFormat = Character.isLetter(workValue.charAt(1));
					if (oldFormat) { // OK => build new format...
						StringBuilder convert = new StringBuilder(8);
						convert.append(0).append (workValue.substring(2,6)).append(workValue.charAt(0)).append(workValue.charAt(workValue.length()-1)); //$SUP-AVI$
						workValue = new String (convert);
					}
					//work value has always new format
					final int [] factors = {8, 7, 6, 5, 4, 3, 2};
					final int [] products = Mathfunctions.multiply(factors, CharSequenceHelper.toIntArray(workValue.substring(0, workValue.length() -2)));
					final int sum = Mathfunctions.sumOfNumbers(products, 0, products.length -1);
					final int checkdigit = sum % 23;
					ok = charIntCheckDigitMapping.get(workValue.charAt(workValue.length()-1)).equals(checkdigit); //$SUP-MANR$ //$SUP-AVI$
				}
			}
			else if (this.value.startsWith("IT")) { // IT - Italien
				if (this.value.length() == 13) {
					final int notNull = Integer.parseInt(this.value.substring(2,9),10);
					final int notAllValues = Integer.parseInt(this.value.substring(10,12),10);
					if (0 != notNull && // special check for italian numbers
						(0 == notAllValues || (notAllValues > 100 && (notAllValues != 120 && notAllValues != 121))) 
					   ) {
						final int [] factors = {1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1};
						final int [] products = Mathfunctions.multiply(factors, CharSequenceHelper.toIntArray(value.substring(2)));
						final int [] sumOfDigits = Mathfunctions.sumOfDigits(products);
						int sum = 0;
						for (final int summand : sumOfDigits) {
							sum += summand;
						}
						int checkdigit = 10 - (sum % 10);
						if (10 == checkdigit) {
							checkdigit = 0;
						}
						ok = Integer.parseInt(this.value.substring(this.value.length()-1)) == checkdigit;
					}
				}
			}
			else if (this.value.startsWith("LV")) { // LV - Lettland
				if (this.value.length() == 13) {
					ok = true;
				}
			}
			else if (this.value.startsWith("LT")) { // LT - Litauen
				if (this.value.length() == 11 || this.value.length() == 14) {
					ok = true;
				}
			}
			else if (this.value.startsWith("LU")) { // LU - Luxemburg
				if (this.value.length() == 10) {
					ok = Integer.parseInt(this.value.substring(this.value.length() -3),10) 
					     == 
					     (Integer.parseInt(this.value.substring(2,this.value.length()-4),10) % 89);						
				}
			}
			else if (this.value.startsWith("MT")) { // MT - Malta
				if (this.value.length() == 10) {
					ok = true;
				}
			}
			else if (this.value.startsWith("NL")) { // NL - Niederlande
				if (this.value.length() == 14) {
					final String workValue = this.value.substring(2,9);
					final int [] factors = {9, 8, 7, 6, 5, 4, 3, 2, 1};
					final int [] products = Mathfunctions.multiply(factors, CharSequenceHelper.toIntArray(workValue));
					final int sum = Mathfunctions.sumOfNumbers(products,0, products.length-2);
					final int checkdigit = sum % 11;
					ok = checkdigit == Integer.parseInt(workValue.substring(workValue.length()-1));
				}
			}
			else if (this.value.startsWith("AT")) { // AT - Ã–sterreich
				if (11 == this.value.length() && this.value.startsWith("ATU")) {
					final int [] factors = {1, 2, 1, 2, 1, 2, 1};
					final int [] products = Mathfunctions.multiply(factors, CharSequenceHelper.toIntArray(this.value.substring(3,this.value.length()-2)));
					final int [] sumOfDigits = Mathfunctions.sumOfDigits(products);
					final int checkNumber = 96 - Mathfunctions.sumOfNumbers(sumOfDigits);
					final int checkdigit = checkNumber % 10;
					ok = checkdigit == Integer.parseInt(value.substring(value.length()-1));
				}
			}
			else if (this.value.startsWith("PL")) { // PL - Polen
				if (this.value.length() == 12) {
					final int [] factors = {6, 5, 7, 2, 3, 4, 5, 6, 7};
					final int [] products = Mathfunctions.multiply(factors, CharSequenceHelper.toIntArray(this.value.substring(3,this.value.length()-2)));
					final int sum = Mathfunctions.sumOfNumbers(products);
					final int checkdigit = sum % 11;
					if (1 != checkdigit) {
						ok = checkdigit == Integer.parseInt(value.substring(value.length()-1));
					}
				}
			}
			else if (this.value.startsWith("PT")) { // PT - Portugal
				if (this.value.length() == 11) {
					final int [] factors = {9, 8, 7, 6, 5, 4, 3, 2, 1};
					final int [] products = Mathfunctions.multiply(factors, CharSequenceHelper.toIntArray(this.value.substring(2,this.value.length()-2)));
					final int sum = Mathfunctions.sumOfNumbers(products);
					int checkdigit = 11 - (sum % 11);
					if (9 < checkdigit) {
						checkdigit = 0;
					}
					ok = checkdigit == Integer.parseInt(value.substring(value.length()-1));
				}
			}
			else if (this.value.startsWith("RO")) { // RO - RumÃ¤nien
				if (this.value.length() < 13 && this.value.length() > 2 && this.value.charAt(2) != 0) {
					ok = true;
				}
			}
			else if (this.value.startsWith("SE")) { // SE - Schweden
				if (this.value.length() == 14 && this.value.endsWith("01")) {
					final int [] factors = {2, 1, 2, 1, 2, 1, 2, 1, 2, 1};
					final int [] products = Mathfunctions.multiply(factors, CharSequenceHelper.toIntArray(this.value.substring(3,11)));
					final int [] sumOfDigits = Mathfunctions.sumOfDigits(products);
					ok = 0 == (Mathfunctions.sumOfNumbers(sumOfDigits) % 10);
				}
			}
			else if (this.value.startsWith("SK")) { // SK - Slowakei
				if (this.value.length() == 12) {
					ok = true;
				}
			}
			else if (this.value.startsWith("SI")) { // SI - Slowenien
				if (this.value.length() == 10) {
					if ('0' != this.value.charAt(2)) { // number >= 1000000
						final int [] factors = {8, 7, 6, 5, 4, 3, 2};
						final int [] products = Mathfunctions.multiply(factors, CharSequenceHelper.toIntArray(this.value.substring(2,this.value.length()-2)));
						final int sum = Mathfunctions.sumOfNumbers(products);
						final int mod11 = sum % 11;
						int checkdigit = 11 - mod11;
						if  (10 == mod11) {
							checkdigit = 0;
						}
						ok = checkdigit == Integer.parseInt(value.substring(value.length()-1));
					}
				}
			}
			else if (this.value.startsWith("ES")) { // ES - Spanien
				if (this.value.length() == 11) {
					if (Character.isDigit(value.charAt(2))) { // nat. Person
						final IIdentityDocument dni = PersonalIdentityCardFactory.createSpanishDocumentoNacionalDeIdentidadInstance();
						dni.setCompleteValue(value.substring(2));
						ok = dni.isChecknumberCorrect();
					}
					else { // Firma
						final int [] factors = {2, 1, 2, 1, 2, 1, 2};
						final int products [] = Mathfunctions.multiply (factors, CharSequenceHelper.toIntArray(this.value.substring(3,this.value.length()-2)));
						final int sum = Mathfunctions.sumOfNumbers(products);
						final int sumOfDigits = Mathfunctions.sumOfDigits (sum);
						final int checkdigit = 10 - ( 10 % sumOfDigits);
						ok = checkdigit == Integer.parseInt(value.substring(value.length()-1));
					}
				}
			}
			else if (this.value.startsWith("CZ")) { // CZ - Tschechische Republik
				if (this.value.length() == 10 || this.value.length() == 11 || this.value.length() == 12) {
					ok = true;
				}
			}
			else if (this.value.startsWith("HU")) { // HU - Ungarn
				if (this.value.length() == 10) {
					ok = true;
				}
			}
			else if (this.value.startsWith("GB")) { // GB - Vereinigtes KÃ¶nigreich von GroÃŸbritannien
				if (this.value.length() == 11 || this.value.length() == 14) {
					ok = true;
				}
				else if (this.value.length() == 7 && (this.value.startsWith("GBGD") || this.value.startsWith("GBHA"))) {// Gouvenment
					ok = true;
				}
			}
			else if (this.value.startsWith("CY")) { // CY - Zypern
				if (this.value.length() == 11 || Character.isLetter(this.value.charAt(this.value.length() -1))) { //$SUP-AVI$
					ok = true;
				}
			}
		  }
  	    }
		catch (NumberFormatException noVATRegNo) {
			ok = false;
		}
		return ok;
	}

	/*
	 * <span lang='en'>
	 * Set the complete value with leading ISO country code
	 * </span>
	 * @param String[] with ISO country code at first index, rest at second index
	 */
	public void setCompleteValue (final String[] value) {
		this.setCompleteValue(value[0]+value[1]);
	}

	/**
	 * <span lang='en'>
	 * Set the complete value with leading ISO country code
	 * </span>
	 */
	public void setCompleteValue (String value) {
		value = value.toUpperCase(); // Characters f.e. Ireland will be upper
		
		this.value = value;
	}
	

	/**
	 * <span lang='en'>
	 * Returns the abbreviation for setting locale.
	 * </span>
	 * <span lang='de'>
	 * Liefert die Abkürzung für die gesetzte Locale.
	 * </span>
	 * @return abbr
	 * @see java.util.Locale#getDefault()
	 */
	public String getI18nAbbr () {
		return this.getI18nAbbr(Locale.getDefault().getCountry());
	}
	
	/**
	 * <span lang='en'>
	 * Returns the abbreviation for giving country.  
	 * </span>
	 * <span lang='de'>
	 * Liefert die Abkürzung für das übergebene Land.
	 * </span>
	 * @return i18n abbreviation of VATRegNo. or if no abbr exists full text or if country has no VATRegNo. an empty string (NullPattern)
	 * @see #getCountry()
	 */
	public String getI18nAbbr (final String twoLetterISO3166CountryCode) {
		String abbr = "";
		if ("BE".equals(twoLetterISO3166CountryCode)) { // BE - BELGIEN
			abbr = "No.TVA BTW-Nr.";
		}
		else if ("BG".equals(twoLetterISO3166CountryCode)) { // BG - BULGARIEN
			abbr = "ДДС";
		}
		else if ("DK".equals(twoLetterISO3166CountryCode)) { // DK - Dänemark
			abbr = "SE-Nr.";
		}
		else if ("DE".equals(twoLetterISO3166CountryCode)) { // DE - Deutschland
			abbr = "USt-IdNr.";
		}
		else if ("EE".equals(twoLetterISO3166CountryCode)) { // EE - Estland
			abbr = "KMKR-number";
		}
		else if ("FI".equals(twoLetterISO3166CountryCode)) { // FI - Finnland
			abbr = "ALV-NRO";
		}
		else if ("FR".equals(twoLetterISO3166CountryCode)) { // FR - Frankreich
			abbr = this.getI18nName(twoLetterISO3166CountryCode);
		}
		else if ("GR".equals(twoLetterISO3166CountryCode)) { // EL - Griechenland !!!statt Country Language!!!
			abbr = "A.φ.M.";
		}
		else if ("IE".equals(twoLetterISO3166CountryCode)) { // IE - Irland
			abbr = "VAT No";
		}
		else if ("IT".equals(twoLetterISO3166CountryCode)) { // IT - Italien
			abbr = "P.IVA";
		}
		else if ("LV".equals(twoLetterISO3166CountryCode)) { // LV - Lettland
			abbr = "PVN reģistrācijas numurs";
		}
		else if ("LT".equals(twoLetterISO3166CountryCode)) { // LT - Litauen
			abbr = "PVM moketojo kodas";
		}
		else if ("LU".equals(twoLetterISO3166CountryCode)) { // LU - Luxemburg
			abbr = this.getI18nName(twoLetterISO3166CountryCode);
		}
		else if ("MT".equals(twoLetterISO3166CountryCode)) { // MT - Malta
			abbr = "VAT No";
		}
		else if ("NL".equals(twoLetterISO3166CountryCode)) { // NL - Niederlande
			abbr = "OB-Nummer";
		}
		else if ("AT".equals(twoLetterISO3166CountryCode)) { // AT - Österreich
			abbr = "UID-Nr.";
		}
		else if ("PL".equals(twoLetterISO3166CountryCode)) { // PL - Polen
			abbr = "NIP";
		}
		else if ("PT".equals(twoLetterISO3166CountryCode)) { // PT - Portugal
			abbr = "NIPC";
		}
		else if ("RO".equals(twoLetterISO3166CountryCode)) { // RO - Rumänien
			abbr = "TVA";
		}
		else if ("SE".equals(twoLetterISO3166CountryCode)) { // SE - Schweden
			abbr = "MomsNr.";
		}
		else if ("SK".equals(twoLetterISO3166CountryCode)) { // SK - Slowakei
			abbr = "IČ DPH";
		}
		else if ("SI".equals(twoLetterISO3166CountryCode)) { // SI - Slowenien
			abbr = "DDV";
		}
		else if ("ES".equals(twoLetterISO3166CountryCode)) { // ES - Spanien
			abbr = "N.IVA";
		}
		else if ("CZ".equals(twoLetterISO3166CountryCode)) { // CZ - Tschechische Republik
			abbr = "DIC";
		}
		else if ("HU".equals(twoLetterISO3166CountryCode)) { // HU - Ungarn
			abbr = this.getI18nName(twoLetterISO3166CountryCode);
		}
		else if ("GB".equals(twoLetterISO3166CountryCode)) { // GB - Vereinigtes Königreich von Großbritannien
			abbr = "VAT Reg.No.";
		}
		else if ("CY".equals(twoLetterISO3166CountryCode)) { // CY - Zypern
			abbr = this.getI18nName(twoLetterISO3166CountryCode);
		}
		return abbr;
	}
	
	/**
	 * <span lang='en'>
	 * Returns the name in giving country. 
	 * </span>
	 * <span lang='de'>
	 * Liefert den Namen für das übergebene Land.
	 * </span>
	 * @return i18n name of VATRegNo. or if coutry has no VATRegNo. an empty string (NullPattern)
	 * @see #getCountry()
	 */
	public String getI18nName (final String twoLetterISO3166CountryCode) {
		String name = "";
		if ("BE".equals(twoLetterISO3166CountryCode)) { // BE - BELGIEN
			name = "le numéro d’identification à la taxe sur la valeur ajoutée BTW - identificatienummer";
		}
		else if ("BG".equals(twoLetterISO3166CountryCode)) { // BG - BULGARIEN
			name = "Идентификационен номер по ДДС";
		}
		else if ("DK".equals(twoLetterISO3166CountryCode)) { // DK - Dänemark
			name = "momsregistreringsnummer";
		}
		else if ("DE".equals(twoLetterISO3166CountryCode)) { // DE - Deutschland
			name = "Umsatzsteuer-Identifikationsnummer";
		}
		else if ("EE".equals(twoLetterISO3166CountryCode)) { // EE - Estland
			name = "Käibemaksukohustuslase registreeri-misnumber";
		}
		else if ("FI".equals(twoLetterISO3166CountryCode)) { // FI - Finnland
			name = "Arvonlisâverorekisterointi-numero";
		}
		else if ("FR".equals(twoLetterISO3166CountryCode)) { // FR - Frankreich
			name = "le numéro d’identification à la taxe sur la valeur ajoutée";
		}
		else if ("GR".equals(twoLetterISO3166CountryCode)) { // EL - Griechenland !!!statt Country Language!!!
			name = "Αριθμός Φορολογικού Μητρώου";
		}
		else if ("IE".equals(twoLetterISO3166CountryCode)) { // IE - Irland
			name = "value added tax identification number";
		}
		else if ("IT".equals(twoLetterISO3166CountryCode)) { // IT - Italien
			name = "il numero di registrazione IVA";
		}
		else if ("LV".equals(twoLetterISO3166CountryCode)) { // LV - Lettland
			name = "pievienotāsvērtības nodokļa reģistrācijas numurs";
		}
		else if ("LT".equals(twoLetterISO3166CountryCode)) { // LT - Litauen
			name = "Pridetines vertes mo-kescio moketojo kodas";
		}
		else if ("LU".equals(twoLetterISO3166CountryCode)) { // LU - Luxemburg
			name = "le numéro d’identification à la taxe sur la valeur ajoutée";
		}
		else if ("MT".equals(twoLetterISO3166CountryCode)) { // MT - Malta
			name = "value added tax identification number";
		}
		else if ("NL".equals(twoLetterISO3166CountryCode)) { // NL - Niederlande
			name = "BTW-identificatienummer";
		}
		else if ("AT".equals(twoLetterISO3166CountryCode)) { // AT - Österreich
			name = "Umsatzsteueridentifikations-nummer";
		}
		else if ("PL".equals(twoLetterISO3166CountryCode)) { // PL - Polen
			name = "Numer identyfikacji podatkowej";
		}
		else if ("PT".equals(twoLetterISO3166CountryCode)) { // PT - Portugal
			name = "o número de identificacao para efeitos do imposto sobre o valor acrescentado";
		}
		else if ("RO".equals(twoLetterISO3166CountryCode)) { // RO - Rumänien
			name = "cod de înregistrare în scopuri de TVA";
		}
		else if ("SE".equals(twoLetterISO3166CountryCode)) { // SE - Schweden
			name = "Registreringsnummer för mervärdesskatt (Momsnummer)";
		}
		else if ("SK".equals(twoLetterISO3166CountryCode)) { // SK - Slowakei
			name = "Identifikačné číslo pre daň z pridanej hodnoty";
		}
		else if ("SI".equals(twoLetterISO3166CountryCode)) { // SI - Slowenien
			name = "davčna številka";
		}
		else if ("ES".equals(twoLetterISO3166CountryCode)) { // ES - Spanien
			name = "el número de identificación a efectos del Impuesto sobre el Valor Anadido";
		}
		else if ("CZ".equals(twoLetterISO3166CountryCode)) { // CZ - Tschechische Republik
			name = "danove identifikacni cislo";
		}
		else if ("HU".equals(twoLetterISO3166CountryCode)) { // HU - Ungarn
			name = "közösségi adószám";
		}
		else if ("GB".equals(twoLetterISO3166CountryCode)) { // GB - Vereinigtes Königreich von Großbritannien
			name = "value added tax registration number";
		}
		else if ("CY".equals(twoLetterISO3166CountryCode)) { // CY - Zypern
			name = "Αριθμός Εγγραφής Φ.Π.Α.";
		}
		return name;
	}

	/**
	 * Return the name of country 
	 * @return county name
	 */
	public String getCountry () {
		if (this.getValue() == null || this.getValue().length()<3) {
			return ""; 
		}
		else {
			return Locale.getDefault().getDisplayCountry(new Locale ("",this.getValue().substring(0,2)));
		}
	}

	@Override
	public String toString () {
		return new StringBuilder (this.getI18nAbbr()).append(' ').append(this.getValue()).toString();
	}
	
	public int hashcode () {
	  /* No two VAT Reg. No. are same; so it is a nice base for hascode */ 
	  return this.getValue().hashCode();
	}

}
